#include <stdint.h>
#include <sys/types.h>
#include <alsa/asoundlib.h>
#include <functional>




bool alsaStart(int channel, int rate, const char *card)
{
    int rev;
    snd_pcm_hw_params_t *hwParms = nullptr;
    snd_pcm_t *pcm = nullptr;
    unsigned int simplerate = rate;
    snd_pcm_uframes_t size = 0;
    int dir;
	unsigned int ui;
    const int silence_size = rate * 10;
    const char *silence = (char *)malloc(silence_size * 2 * channel);
    int writed;
    //snd_pcm_uframes_t frames = 1024;

    rev = snd_pcm_open(&pcm, card,
                       SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
    if (rev <0)
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }
    rev = snd_pcm_hw_params_malloc(&hwParms);
    if(rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }
    
    /*按照默认设置对硬件对象进行设置，并判断是否设置成功*/
    rev = snd_pcm_hw_params_any(pcm, hwParms);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;

    }
    rev = snd_pcm_hw_params_set_access(pcm, hwParms, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (rev < 0)
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }

    /*设置数据编码格式，并判断是否设置成功*/
    rev = snd_pcm_hw_params_set_format(pcm, hwParms,SND_PCM_FORMAT_S16_LE);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }


    rev = snd_pcm_hw_params_set_rate_near(pcm, hwParms, &simplerate, 0);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }
    printf("near simpleate:%d\n", (int)simplerate)
    ;

    rev = snd_pcm_hw_params_set_channels(pcm, hwParms, channel);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }

#if 1
    size = simplerate / 100;
    rev = snd_pcm_hw_params_set_period_size_near(pcm, hwParms, &size, &dir);
    if (rev < 0) 
    {
        printf("AudioPlayer set period_size err\n");
        goto err;
    }
    printf("period size:%d dir:%d\n", (int)size, (int)dir);
#endif

#if 1
	printf("### setbuffer \n");
	size = simplerate;
	rev = snd_pcm_hw_params_set_buffer_size_near(pcm, hwParms, &size);
    if (rev < 0) 
    {
        printf("AudioPlayer set set_buffer_size err\n");
        goto err;
    }
	printf("### setbuffer size:%d\n", (int)size);
#endif

#if 0
	ui = 1000;
	rev = snd_pcm_hw_params_set_buffer_time_near(alsaPCM, hwParms, &ui, &dir);
    if (rev < 0) 
    {
        printf("AudioPlayer set_buffer_time err\n");
        goto err;
    }
	printf("### set_buffer_time size:%d\n", (int)ui);
#endif
    rev = snd_pcm_hw_params(pcm, hwParms);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }

    size = 0;
    snd_pcm_hw_params_get_buffer_size(hwParms, &size);
    printf("alsa hw_params buffer size:%d\n", (int)size);

    rev = snd_pcm_prepare(pcm);
    if (rev < 0) 
    {
        printf("AudioPlayer alsa start err\n");
        goto err;
    }
    snd_pcm_hw_params_free(hwParms);

    writed = snd_pcm_writei(pcm, silence, silence_size);
    printf("Write %d return:%d\n", silence_size, writed);

    free((void*)silence);
    snd_pcm_close(pcm);
    return true;
err:
    if (hwParms) snd_pcm_hw_params_free(hwParms);
    if (pcm) snd_pcm_close(pcm);
    free((void*)silence);
    return false;
}

int main(int argc, char *argv[])
{
    // alsaStart(2, 44100, "default");
    // alsaStart(2, 16000, "bluealsa");
	alsaStart(2, 44100, "bluealsa");
    return 0;
}
